package tv.mineinthebox.essentials.events.entity;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.ProjectileHitEvent;
import org.bukkit.material.MaterialData;
import tv.mineinthebox.essentials.xEssentials;
public class RealisticGlassEvent implements Listener {
private final HashMap<Location, MaterialData> blocks = new HashMap<Location, MaterialData>();
private final HashMap<Location, Block> glasses = new HashMap<Location, Block>();
private final xEssentials pl;
public RealisticGlassEvent(xEssentials pl) {
this.pl = pl;
}
@EventHandler
public void projectiles(ProjectileHitEvent e) {
if(e.getEntity() instanceof Arrow) {
Arrow arrow = (Arrow) e.getEntity();
if(arrow.getShooter() instanceof Player) {
if(hasAttachedGlass(arrow.getLocation().getBlock())) {
storeGlasses(arrow.getLocation().getBlock());
arrow.remove();
destroyRandomGlasses();
}
}
}
}
private boolean hasAttachedGlass(Block block) {
for(BlockFace face : BlockFace.values()) {
if(face != BlockFace.SELF) {
if(block.getRelative(face).getType() == Material.GLASS || block.getRelative(face).getType() == Material.THIN_GLASS || block.getRelative(face).getType() == Material.STAINED_GLASS || block.getRelative(face).getType() == Material.STAINED_GLASS_PANE) {
return true;
}
}
}
return false;
}
private void storeGlasses(Block block) {
for(int X = 0; X < 12;X++) {
for(int Y = 0; Y < 12; Y++) {
for(int Z = 0; Z < 12; Z++) {
Block allplus = block.getWorld().getBlockAt((block.getX()+X), (block.getY()+Y),(block.getZ()+Z));
if(allplus.getType() == Material.GLASS || allplus.getType() == Material.THIN_GLASS || allplus.getType() == Material.STAINED_GLASS || allplus.getType() == Material.STAINED_GLASS_PANE) {
glasses.put(allplus.getLocation(), allplus);
}
Block allmin = block.getWorld().getBlockAt((block.getX()-X), (block.getY()+Y),(block.getZ()-Z));
if(allmin.getType() == Material.GLASS || allmin.getType() == Material.THIN_GLASS || allmin.getType() == Material.STAINED_GLASS || allmin.getType() == Material.STAINED_GLASS_PANE) {
glasses.put(allmin.getLocation(), allmin);
}
Block xmin = block.getWorld().getBlockAt((block.getX()-X), (block.getY()+Y), (block.getZ()+Z));
if(xmin.getType() == Material.GLASS || xmin.getType() == Material.THIN_GLASS || xmin.getType() == Material.STAINED_GLASS || xmin.getType() == Material.STAINED_GLASS_PANE) {
glasses.put(xmin.getLocation(), xmin);
}
Block zmin = block.getWorld().getBlockAt((block.getX()+X), (block.getY()+Y), (block.getZ()-Z));
if(zmin.getType() == Material.GLASS || zmin.getType() == Material.THIN_GLASS || zmin.getType() == Material.STAINED_GLASS || zmin.getType() == Material.STAINED_GLASS_PANE) {
glasses.put(zmin.getLocation(), zmin);
}
}
}
}
}
private void destroyRandomGlasses() {
for(int i = 0; i < glasses.size();i++) {
Location[] locs = glasses.keySet().toArray(new Location[glasses.size()]);
Location loc = locs[i];
Block block = glasses.get(loc);
blocks.put(loc, block.getState().getData());
block.getWorld().playEffect(loc, Effect.STEP_SOUND, block.getType());
glasses.remove(loc);
block.breakNaturally();
}
glasses.clear();
}
@EventHandler
public void entityFall(EntityDamageEvent e) {
if(e.getCause() == DamageCause.FALL) {
if(e.getEntity().getLocation().getBlock().getRelative(BlockFace.DOWN).getType() == Material.GLASS || e.getEntity().getLocation().getBlock().getRelative(BlockFace.DOWN).getType() == Material.STAINED_GLASS) {
storeGlasses(e.getEntity().getLocation().getBlock().getRelative(BlockFace.DOWN));
destroyRandomGlasses();
}
}
}
public void startRegen() {
Bukkit.getScheduler().scheduleSyncRepeatingTask(pl, new Runnable() {
@SuppressWarnings("deprecation")
@Override
public void run() {
if(!blocks.isEmpty() || blocks.size() != 0) {
Iterator<Entry<Location, MaterialData>> it = blocks.entrySet().iterator();
it.hasNext();
Map.Entry<Location, MaterialData> its = (Map.Entry<Location, MaterialData>) it.next();
Location loca = (Location) its.getKey();
MaterialData blockType = (MaterialData) its.getValue();
loca.getBlock().setTypeId(blockType.getItemTypeId());
loca.getBlock().setData(blockType.getData());
it.remove();
blocks.remove(loca);
}
}
}, 10, 100);
}
private String serializeLocation(Location loc) {
return loc.getWorld().getName() + ","+loc.getBlockX()+","+loc.getBlockY()+","+loc.getBlockZ();
}
@SuppressWarnings("deprecation")
private String serializeMaterialData(MaterialData data) {
return data.getItemType().getId()+":"+data.getData();
}
private Location deSerializeLocation(String loc) {
String[] args = loc.split(",");
String worldName = args[0];
int x = Integer.parseInt(args[1]);
int y = Integer.parseInt(args[2]);
int z = Integer.parseInt(args[3]);
return new Location(Bukkit.getWorld(worldName), x, y , z);
}
@SuppressWarnings("deprecation")
private MaterialData deSerializeMaterialData(String data) {
String[] values = data.split(":");
int id = Integer.parseInt(values[0]);
byte sub = Byte.parseByte(values[0]);
return new MaterialData(id, sub);
}
public void saveGlassBlocks() {
try {
File f = new File(pl.getDataFolder() + File.separator + "RealisticGlass.db");
FileConfiguration con = YamlConfiguration.loadConfiguration(f);
Iterator<Entry<Location, MaterialData>> it = blocks.entrySet().iterator();
List<String> locs = new ArrayList<String>();
List<String> blocks = new ArrayList<String>();
while(it.hasNext()) {
Map.Entry<Location, MaterialData> map = it.next();
locs.add(serializeLocation(map.getKey()));
blocks.add(serializeMaterialData(map.getValue()));
it.remove();
}
con.set("locations", locs);
con.set("blocks", blocks);
con.save(f);
} catch(Exception e) {
e.printStackTrace();
}
}
public void loadGlassBlocks() {
try {
File f = new File(pl.getDataFolder() + File.separator + "RealisticGlass.db");
if(f.exists()) {
FileConfiguration con = YamlConfiguration.loadConfiguration(f);
for(int i = 0; i < con.getStringList("locations").size();i++) {
Location loc = deSerializeLocation(con.getStringList("locations").get(i));
MaterialData data = deSerializeMaterialData(con.getStringList("blocks").get(i));
blocks.put(loc, data);
}
f.delete();
}
} catch(Exception e) {
e.printStackTrace();
}
}
}